package com.cloudlead.web.resource;

import org.apache.log4j.Logger;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import java.beans.PropertyDescriptor;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import static java.lang.Math.*;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

public class UtilFuns {
    public static final Logger log = Logger.getRootLogger();

    static final String[] dw = new String[]{"", "THOUSAND", "MILLION", "BILLION"};
    static final String[] zr1 = new String[]{"", "TEN", "TWENTY", "THIRTY", "FORTY", "FIFTY", "SIXTY", "SEVENTY", "EIGHTY", "NINETY"};
    static final String[] zr2 = new String[]{
            "", "", "", "", "", "", "", "", "", "",
            "TEN", "ELEVEN", "TWELVE", "THIRTEEN", "FOURTEEN", "FIFTEEN", "SIXTEEN", "SEVENTEEN", "EIGHTEEN", "NINETEEN"};
    static final String[] zr3 = new String[]{"", "ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE"};

    public static final SimpleDateFormat dfTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public static final SimpleDateFormat dfDate = new SimpleDateFormat("yyyy-MM-dd");
    public static final SimpleDateFormat dfDate1 = new SimpleDateFormat("yyyyMMddHHmmss");

    /**
     * 根据登录时确定的时间差,取数据库时间
     *
     * @param req 参数 HttpServletRequest
     * @return Date
     */
    static public Date getDbTime(HttpServletRequest req) {
        ServletContext context = req.getSession().getServletContext();
        Date localdate = new Date();
        try {
            long timeDiff = (Long) context.getAttribute("SYS_DbTimeDiff");
            return new Date(localdate.getTime() + timeDiff);
        } catch (Exception e) {
            return localdate;
        }
    }

    static public Integer getWeekOfDate(Date date){
        Calendar c = new GregorianCalendar();
        c.setFirstDayOfWeek(Calendar.SUNDAY);
        c.setMinimalDaysInFirstWeek(1);
        c.setTime (date);
        return(c.get(Calendar.WEEK_OF_YEAR));
    }


    static public Integer getMonthOfDate(Date date){
        Calendar c = new GregorianCalendar();
        c.setFirstDayOfWeek(Calendar.SUNDAY);
        c.setMinimalDaysInFirstWeek(1);
        c.setTime (date);
        return(c.get(Calendar.MONTH));
    }


    static public Integer getYearOfDate(Date date){
        Calendar c = new GregorianCalendar();
        c.setFirstDayOfWeek(Calendar.SUNDAY);
        c.setMinimalDaysInFirstWeek(1);
        c.setTime (date);
        return(c.get(Calendar.YEAR));
    }
    /**
     * 从资源文件中取出key对应的本地语言
     *
     * @param req HttpServletRequest
     * @param key String
     * @return String
     */
/*    static public String getLocalMessage(HttpServletRequest req, String key) {
        ApplicationContext context = (ApplicationContext) req.getSession().getAttribute("context");
        try {
            return context.getMessage(key, null, req.getLocale());
        } catch (Exception e) {
            return "";
        }
    }
**/
    static public String nextLine() {
        return System.getProperty("line.separator");
    }

    /**
     * SplitStr 功能：将数组合并为一个字符串
     *
     * @param aStr      String[]  要合并数组
     * @param splitFlag String  设置分割字符
     * @return String 要合并数组
     */
    static public String joinStr(String[] aStr, String splitFlag) {
        StringBuffer sBuffer = new StringBuffer();
        if (aStr != null) {
            for (String anAStr : aStr) {
                sBuffer.append(anAStr).append(splitFlag);
            }
            sBuffer.delete(sBuffer.length() - 1, sBuffer.length()); //去掉最后的分隔符 splitFlag
        } else {
            sBuffer = sBuffer.append("");
        }
        return sBuffer.toString();
    }

    /**
     * sysTime 功能：返回系统时间
     *
     * @param strStyle string 设置返回系统时间样式
     * @return string 返回系统时间样式
     */
    static public String sysTime(String strStyle) {
        Date date = new Date();
        SimpleDateFormat dformat = new SimpleDateFormat(strStyle);
        return dformat.format(date);
    }

    /**
     * convertNull 功能：用于转换为null的字段。
     *
     * @param strvalue String  设置要转换的字符串
     * @return String 不为“null”的返回原串；为“null”返回""。
     */
    public static String convertNull(String strvalue) {
        return strvalue == null || strvalue.equalsIgnoreCase("null") ? "" : strvalue;
    }

    public static String quotedStr(String strvalue){
        if (strvalue==null) return "''";
        return "'"+strvalue.replaceAll("'","''")+"'";
    }
    /**
     * formatDate 功能：用于格式化输出日期类型
     *
     * @param date       Date 传入的日期
     * @param dateFormat String传入的日期格式
     * @return string
     */
    public static String formatDate(Date date, String dateFormat) {
        if (date == null) {
            return "";
        }
        SimpleDateFormat format = new SimpleDateFormat(dateFormat);
        return format.format(date);
    }

    public static String getUSDate(Date date) {
        //设置时区
        Locale localeEN = new Locale("en", "US");
        // 获得美国时间格式
        DateFormat DateFormatEN = DateFormat.getDateInstance(DateFormat.MEDIUM, localeEN);
        //自定义日期格式
        SimpleDateFormat selfDateFormat = new SimpleDateFormat("yyMMddHHmmss");
        if (date == null) return "";
        if (date.equals("null") || date.equals("")) {
            return "";
        } else {
            return DateFormatEN.format(date);
        }
    }

    /**
     * replaceEspecialCharacter 功能：替换在网页上显示有问题的特殊字符
     *
     * @param s 传入的参数
     * @return String
     */
    public static String replaceEspecialCharacter(String s) {
        if (s != null && s.length() > 0) {
            if (s.indexOf("&") >= 0) {
                s = s.replaceAll("&", "&amp;");
            }
            if (s.indexOf(">") >= 0) {
                s = s.replaceAll(">", "&gt;");
            }
            if (s.indexOf("<") >= 0) {
                s = s.replaceAll("<", "&lt;");
            }
        }
        return s;
    }

    public static String FormatHtmlCode(String Source) {
        String st1 = Source.replaceAll(" ", "&nbsp;");
        String st2 = st1.replaceAll("\r\n", "<br>").replaceAll("\n", "<br>");
        return st2;
    }

    public static String FormatHtmlReCode(String Source) {
        Source = Source.replaceAll("<br>", "\n");
        Source = Source.replaceAll("&nbsp;", " ");
        return Source;
    }

    public static void FormatHtmlFields(HashMap dataMap,String fieldList)
    {
        String sFldList= ","+fieldList.toUpperCase()+",";
        try {
            for(Object o:dataMap.keySet()) {
                String fldName=(String)o;
                if (sFldList.indexOf(","+fldName.toUpperCase()+",")>=0){
                    String sVal = (String)dataMap.get(o);
                    if (sVal!=null)
                        dataMap.put(o,FormatHtmlCode(UtilFuns.replaceEspecialCharacter(sVal)));
                }
            }
        } catch (Exception e) {
            UtilFuns.log.error(e);
        }
    }
    
    /**
     * sayEngForNum 功能：将数字转换为英文说法
     *
     * @param sNum 传入的数值
     * @return string
     */
    static public String sayEngForNum(String sNum) {
        String sRet, lStr, rStr;
        sRet = "";
        rStr = "";
        String sTmp = sNum.replace(".", "/");
        lStr = sTmp.split("/")[0];
        if (sTmp.split("/").length > 1) rStr = sTmp.split("/")[1];
        int secCount = ((lStr.length() / 3) + (lStr.length() % 3 == 0 ? 0 : 1));
        int oldLen = lStr.length();
        for (int i = 0; i < secCount * 3 - oldLen; i++) {
            lStr = "0" + lStr;
        }
        for (int i = 0; i < secCount; i++) {
            sTmp = lStr.substring((secCount - i - 1) * 3, (secCount - i - 1) * 3 + 3);
            if (i == 0) {
                sRet = w3(sTmp);
            } else {
                sRet = w3(sTmp) + " " + dw[i] + " " + sRet;
            }
        }
        if (!rStr.equals("")) {
            sRet = sRet + " AND CENTS " + w2("$" + rStr + "0") + " ";
        }
        return sRet;
    }

    static private String w3(String sNum) {
        if (sNum.substring(0, 1).equals("0")) {
            return w2(sNum);
        } else if (sNum.substring(1, 3).equals("00")) {
            return zr3[Integer.parseInt(sNum.substring(0, 1))] + " " + "HUNDRED";
        } else {
            return zr3[Integer.parseInt(sNum.substring(0, 1))] + " " + "HUNDRED" + " AND " + w2(sNum);
        }
    }

    static private String w2(String sNum) {
        if (sNum.substring(1, 2).equals("0")) {
            return zr3[Integer.parseInt(sNum.substring(2, 3))];
        } else if (sNum.substring(1, 2).equals("1")) {
            return zr2[Integer.parseInt(sNum.substring(1, 3))];
        } else if (sNum.substring(2, 3).equals("0")) {
            return zr1[Integer.parseInt(sNum.substring(1, 2))];
        } else {
            return zr1[Integer.parseInt(sNum.substring(1, 2))] + " " + zr3[Integer.parseInt(sNum.substring(2, 3))];
        }
    }

    public static String digitUppercase(double n){
        String fraction[] = {"角", "分"};
        String digit[] = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" };
        String unit[][] = {{"元", "万", "亿"},{"", "拾", "佰", "仟"}};
        String head = n < 0? "负": "";
        n = Math.abs(n);
        String s = "";
        for (int i = 0; i < fraction.length; i++) {
            s += (digit[(int)(Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", "");
        }
        if(s.length()<1){
            s = "整";
        }
        int integerPart = (int)Math.floor(n);
        for (int i = 0; i < unit[0].length && integerPart > 0; i++) {
            String p ="";
            for (int j = 0; j < unit[1].length && n > 0; j++) {
                p = digit[integerPart%10]+unit[1][j] + p;
                integerPart = integerPart/10;
            }
            s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s;
        }
        return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整");
    }


    /**
     * parseDate 功能:将字符串转换为日期格式
     *
     * @param dateStr    传入的字符串
     * @param dateFormat 设定的日期格式
     * @return Date
     */
    public static Date parseDate(String dateStr, String dateFormat) {
        if (convertNull(dateStr).equals("")) {
            return null;
        }
        Date date = null;
        try {
            SimpleDateFormat format = new SimpleDateFormat(dateFormat);
            date = format.parse(dateStr);
        } catch (ParseException e) {
            log.error(e.getMessage());
        }
        return date;
    }

    /**
     * 获得指定日期的后一天
     */
    public static Date getDateAfter(Date date,int day){
        if (date==null) return null;
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int cDay=c.get(Calendar.DATE);
        c.set(Calendar.DATE,cDay+day);
        return c.getTime();
    }
    /**
     * parseInt 功能：将字符类型转换为整型
     *
     * @param s 传入的参数
     * @return 返回整型
     */
    public static Integer parseInt(String s) {
        int i = 0;
        if (convertNull(s).equals("")) {
            return null;
        }
        try {
            i = Integer.parseInt(s);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return i;
    }

    /**
     * parseDouble 功能：将字符类型转换为double型
     *
     * @param s 传入的参数
     * @return 返回double
     */
    public static Double parseDouble(String s) {
        double i = 0;
        if (convertNull(s).equals("")) {
            return null;
        }
        try {
            i = Double.parseDouble(s);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return i;
    }

    /**
     * parseFloat 功能：将字符类型转换为double型
     *
     * @param s 传入的参数
     * @return 返回double
     */
    public static Float parseFloat(String s) {
        float i = 0;
        if (convertNull(s).equals("")) {
            return null;
        }
        try {
            i = Float.parseFloat(s);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return i;
    }
    /**
     * getAryValue 功能：通过传入的数组下标，获得值，避免数组越界的问题
     *
     * @param tmpAry 传入的数组
     * @param i      传入的下标
     * @return String
     */
    public static String getAryValue(String[] tmpAry, int i) {
        return i < tmpAry.length ? convertNull(tmpAry[i]) : "";
    }


    /**
     * 从类似于target=ebooking/ViewOrder.do&userId=TEST&keyName=order_no&keyValue=20061226001中按名字取值
     *
     * @param AParaStr String
     * @param AName    String
     * @return value
     */
    static public String getParaStr(String AParaStr, String AName) {
        int idx = AParaStr.toUpperCase().indexOf(AName.toUpperCase());
        if (idx >= 0) {
            int NextIdx = AParaStr.indexOf('&', idx);
            return NextIdx >= 0 ?
                    AParaStr.substring(idx + AName.length() + 1, NextIdx) :
                    AParaStr.substring(idx + AName.length() + 1);
        } else {
            return "";
        }
    }

    static public Object getApplicationValue(ServletContext servletContext, String key) {
        synchronized (servletContext) {
            return servletContext.getAttribute(key);
        }
    }

    /**
     * 格式化double类型
     *
     * @param number 数值参数
     * @return 格式化后的String
     */
    public static String formatDouble(double number) {
        DecimalFormat df = new DecimalFormat("###.000");
        return df.format(number);
    }

    public static double round(double value,int scale){
        return new BigDecimal(Double.toString(value)).setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    public static String changeCharset(String str,String codeType){
        byte[] bs = str.getBytes();
        String sTmp="";
        try{
            sTmp=new String(bs, codeType);
        }catch(Exception e){}
        return sTmp;
    }
    public static String xssFilter(String value) {
        if (value == null) {
            return null;
        }
        StringBuffer result = new StringBuffer(value.length());
        for (int i = 0; i < value.length(); ++i) {
            switch (value.charAt(i)) {
                case '<':
                    result.append("&lt;");
                    break;
                case '>':
                    result.append("&gt;");
                    break;
                case '"':
                    result.append("&quot;");
                    break;
                case '\'':
                    result.append("&#39;");
                    break;
                case '%':
                    result.append("&#37;");
                    break;
                case ';':
                    result.append("&#59;");
                    break;
                case '(':
                    result.append("&#40;");
                    break;
                case ')':
                    result.append("&#41;");
                    break;
                case '&':
                    result.append("&amp;");
                    break;
                case '+':
                    result.append("&#43;");
                    break;
                default:
                    result.append(value.charAt(i));
                    break;
            }
        }
        return result.toString();
    }

    public static String keywordFilter(String value, String keyWords, Boolean withSpacechar) {
        if (value == null) {
            return null;
        }
        int idx = 0;
        String strRlt = value;
        String[] arrKeyWord = keyWords.split(" ");
        for (int i = 0; i < arrKeyWord.length; i++) {
            String checkWord = arrKeyWord[i].toLowerCase();
            if (!checkWord.equalsIgnoreCase("and")) {
                if (withSpacechar) checkWord = " " + checkWord + " ";
                idx = strRlt.toLowerCase().indexOf(checkWord);
                if (idx >= 0) {
                    strRlt = strRlt.substring(0, idx) + " "+strRlt.substring(idx+checkWord.length());
                }
            }
        }
        return strRlt;
    }

    public static String getRandomNumber(int len){
        String strRlt="";
        for (int i=0;i<len;i++){
           strRlt += (int)(random()*10);
        }
        return strRlt;
    }

    public static String DelTrailReturn(String str)
    {
        if (str==null) return null;
        String sRlt=str;
        while (sRlt.endsWith("\r\n")) sRlt=sRlt.substring(0,sRlt.length()-2);
        while (sRlt.endsWith("\r")) sRlt=sRlt.substring(0,sRlt.length()-1);
        while (sRlt.endsWith("\n")) sRlt=sRlt.substring(0,sRlt.length()-1);
        return sRlt;
    }

    private static final boolean isChinese(char c) {
      Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
      if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
        || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
        || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
        || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
        || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
        || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
       return true;
      }
      return false;
     }

    public static final boolean isChinese(String strName) {
      char[] ch = strName.toCharArray();
      for (int i = 0; i < ch.length; i++) {
       char c = ch[i];
       if (isChinese(c)) {
        return true;
       }
      }
      return false;
     }

    public static String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (ip.equals("0:0:0:0:0:0:0:1")) {
            ip = "LOCAL";
        }
        return ip;
    }

    public static String SetQueryParams(String fieldName,String val){
        return SetQueryParams(fieldName, val,"=");
    }
    public static String SetQueryParams(String fieldName,String val,final String op){
        if (val==null || val.equals("")) return "";
        if (op.equalsIgnoreCase("like")) val="%"+val+"%";
        return " and "+fieldName+" "+op+quotedStr(val);
    }

    public static String SetDateQueryParams(String fieldName,String date1,String date2){
        String sRlt="";
        if (date1!=null && !date1.equals(""))
            sRlt += " and "+fieldName+">=to_date("+quotedStr(date1)+",'yyyy-MM-dd')";
        if (date2!=null && !date2.equals(""))
            sRlt += " and "+fieldName+"<to_date("+quotedStr(date2)+",'yyyy-MM-dd')+1";
        return sRlt;
    }

    public static String SetQueryParams(String fieldName,Object val,List paraValList){
        return  SetQueryParams(fieldName,val,paraValList,"=");
    }
    public static String SetQueryParams(final String fieldName,Object val,List paraValList,final String op){
        if (val==null) return "";
        if ((val instanceof String) && val.equals("")) return "";
        if (fieldName.equalsIgnoreCase("status") && val.equals("ALL")) return "";
        if (op.equalsIgnoreCase("like")) val="%"+((String)val).trim()+"%";
        paraValList.add(val);
        return " and "+fieldName+" "+op+" ?";
    }

    public static String getArrayParameter(String paramName,HttpServletRequest request){
        String values="";
        if (request.getParameterMap().containsKey(paramName))
            values+=UtilFuns.convertNull(request.getParameter(paramName));
        else if (request.getParameterMap().containsKey(paramName+"[]"))
            for (String item:request.getParameterValues(paramName+"[]")){
                values+=","+item;
            }
        if (values.startsWith(",")) values=values.substring(1);
        return values;
    }

    public static String SetMultiQueryParams(String fieldName,String paramName,HttpServletRequest request){
        String values=getArrayParameter(paramName,request);
        return values.equals("")?"":(" and "+fieldName+" in ('"+values.replaceAll(",","','")+"')");
    }

    public static String getInCondition(String keyField,String keyValues){
        String[] valList=keyValues.split(",");
        if (valList.length<=100) return " "+keyField+" in ("+keyValues+")";
        StringBuilder sb=new StringBuilder();
        for (int i=0;i<valList.length;i++){
            if (i%1000==0)
                sb.append(") or "+keyField+" in ("+valList[i]);
            else
                sb.append(","+valList[i]);
        }
        sb.append(")");
        sb.delete(0,5);
        return "("+sb.toString()+")";
    }

    /**
     * 从HashMap数据记录中读取字段值
     * @param record
     * @param fieldName
     * @param params
     * @return
     */
    public static String GetFieldValue(Object record,String fieldName,Object... params){
        HashMap<String,Object> map = (HashMap<String,Object>)record;
        if (!map.containsKey(fieldName)) fieldName=fieldName.toUpperCase();
        Object obj=map.get(fieldName);
        String sRlt=convertNull(String.valueOf(obj));
        if (params.length>0 && (Boolean)params[0])
            sRlt=quotedStr(sRlt);
        return sRlt;
    }

    public static Object GetFieldObjValue(Object record,String fieldName){
        HashMap<String,Object> map = (HashMap<String,Object>)record;
        if (!map.containsKey(fieldName)) fieldName=fieldName.toUpperCase();
        return map.get(fieldName);
    }

    public static String FormatSqlStrEx(String fieldValue){
        String sRlt=fieldValue.replaceAll("'","''");
        sRlt=sRlt.replaceAll(":","'||chr(58)||'");
        sRlt=sRlt.replaceAll("\"","'||chr(34)||'");
        sRlt=sRlt.replaceAll("\r\n","'||chr(34)||'");
        sRlt=sRlt.replaceAll("`","").replaceAll("\r","").replaceAll("\n","");
        return "'"+sRlt+"'";
    }

    public static HashMap StringToHashMap(String sValue,String sSplit){
        HashMap rltMap= new HashMap();
        while (true){
            int idx = sValue.indexOf(sSplit);
            if (idx<0) break;
            String sTmp= sValue.substring(0,idx);
            if (sTmp.indexOf("=")>0)
                rltMap.put(sTmp.substring(0,sTmp.indexOf("=")),sTmp.substring(sTmp.indexOf("=")+1));
            sValue=sValue.substring(idx+sSplit.length());
        }
        if (sValue.indexOf("=")>0)
            rltMap.put(sValue.substring(0,sValue.indexOf("=")),sValue.substring(sValue.indexOf("=")+1));
        return rltMap;
    }

    //压缩
    public static String compress(String str) throws IOException {
        if (str == null || str.length() == 0) {
            return str;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        GZIPOutputStream gzip = new GZIPOutputStream(out);
        gzip.write(str.getBytes());
        gzip.close();
        return out.toString("ISO-8859-1");
    }

    // 解压缩
    public static String uncompress(String str) throws IOException {
        if (str == null || str.length() == 0) {
            return str;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ByteArrayInputStream in = new ByteArrayInputStream(str
                .getBytes("ISO-8859-1"));
        GZIPInputStream gunzip = new GZIPInputStream(in);
        byte[] buffer = new byte[256];
        int n;
        while ((n = gunzip.read(buffer))>= 0) {
            out.write(buffer, 0, n);
        }
        // toString()使用平台默认编码，也可以显式的指定如toString(&quot;GBK&quot;)
        return out.toString();
    }
    

}
